#include "bsp_gpio.h"

/**
 * @brief  GPIO的中断功能配置   //这里是设置中断的模式   但开关中断不是这个函数
 * @param  base 要配置的IO所在的GPIO组
 * @param  pin  要配置的GPIO脚号
 * @param  pin_int_mode 中断模式   
 * @return 无
 */
void gpio_intconfig(GPIO_Type * base,int pin,gpio_interrupt_mode_t pin_int_mode)
{
    volatile uint32_t *icr;  //这里是一种类型的指针  和指向对象的类型相同
    uint32_t icrShift;

    icrShift=pin;
    base->EDGE_SEL &= ~(1U <<pin);  //这里表示不双边沿触发  //相应的位如果被置位那么就表示双边沿触发

    if(pin <16)
    {//0~15
        icr=&(base->ICR1);  //这里是设置触发方式   把这个变量的地址取出来  即icr指向
    }
    else
    {//16~31
        icr=&(base->ICR2);
        icrShift-=16;   //这里不知道是啥意思
    }

    switch (pin_int_mode)
    {
        case kGPIO_IntLowLevel: *icr &= ~(3U << (2* icrShift)); break;   //icrShift这里是通过pin赋值过来的   这里将两个位全部清零
        case kGPIO_IntHighLevel:*icr = (*icr &(~(3U<<(2* icrShift)))) | (1U<<(2* icrShift)) ;break;      //两位置1
        case kGPIO_IntRisingEdge:*icr = (*icr &(~(3U<<(2* icrShift)))) | (2U<<(2* icrShift)) ;break;
        case kGPIO_IntFallingEdge:*icr = (*icr &(~(3U<<(2* icrShift)))) | (3U<<(2* icrShift)) ; break;
        case kGPIO_IntRisingOrFallingEdge: base->EDGE_SEL |= (1U << pin); break;  //表示双边触发
        default:break;
    }
}

/**
 * @brief  使能GPIO的中断功能
 * @param  base 要使能的IO所在的GPIO组
 * @param  pin  要使能的GPIO脚号
 * @return 无
 */
void gpio_enableint(GPIO_Type * base,int pin)
{
    base->IMR |= (1<<pin);  //IMR中的位置位表示开中断
}

/**
 * @brief  禁止GPIO的中断功能
 * @param  base 要禁止的IO所在的GPIO组
 * @param  pin  要禁止的GPIO脚号
 * @return 无
 */
void gpio_disableint(GPIO_Type * base,int pin)
{
    base->IMR &= ~(1<<pin);  //IMR中的位置位表示开中断
}

/**
 * @brief  清除中断标志位(写1清除)
 * @param  base 要清除的IO所在的GPIO组
 * @param  pin  要清除的GPIO脚号
 * @return 无
 */
void gpio_clearintflags(GPIO_Type * base,int pin)
{
    base->ISR |= (1 << pin);  //写1清除中断
}

/**
 * @brief  GPIO初始化
 * @param  base 要初始化的GPIO组
 * @param  pin  要初始化的GPIO在组内的编号 
 * @param  config GPIO配置结构体
 * @return 无
 */
void gpio_init(GPIO_Type * base,int pin,gpio_pin_config_t * config)
{
    base->IMR &= ~(1U << pin);     //将pin脚的中断关掉

    if(config->direction==kGPIO_DigitalInput)
    {   //输入
        base->GDIR &= ~(1<<pin); //
    }
    else //输出
    {
        base->GDIR |= 1<<pin; //
        gpio_pinwrite(base,pin,config->outputLogic);  //默认输出的电平
    }
    gpio_intconfig(base,pin,config->interruptMode);   //中断功能配置
}

/**
 * @brief 读取指定GPIO的电平值
 * @param base :要读取的GPIO组
 * @param pin:要读取的GPIO脚号
 * @retval :无
 */
int gpio_pinread(GPIO_Type * base,int pin)
{
    return ( ((base->DR)>>pin) & 0x1 );   //输出时也是DR
}

/**
 * @brief 指定GPIO输出高或者低电平
 * @param base :要输出的GPIO组
 * @param pin:要输出的GPIO脚号
 * @param value:要输出的电平  1输出高点平  0输出低电平
 * @retval :无
 */
void gpio_pinwrite(GPIO_Type * base,int pin,int value)
{
    if(value==0U)
    {
        base->DR &= ~(1U << pin);
    }
    else
    {
        base->DR |= (1U << pin);
    }
}